package com.atguigu.gmall.order.service.impl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.atguigu.gmall.common.constant.RedisConst;
import com.atguigu.gmall.common.utils.HttpClientUtil;
import com.atguigu.gmall.model.cart.CartInfo;
import com.atguigu.gmall.model.enums.OrderStatus;
import com.atguigu.gmall.model.order.OrderDetail;
import com.atguigu.gmall.model.order.OrderInfo;
import com.atguigu.gmall.order.mapper.CartInfoMapper;
import com.atguigu.gmall.order.mapper.OrderDetailsMapper;
import com.atguigu.gmall.order.mapper.OrderInfoMapper;
import com.atguigu.gmall.order.service.CartAsyncService;
import com.atguigu.gmall.order.service.OrderInfoService;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

@Service
public class OrderInfoServiceImpl implements OrderInfoService {

    @Autowired
    private OrderInfoMapper orderInfoMapper;

    @Autowired
    private OrderDetailsMapper orderDetailsMapper;

    @Autowired
    private CartAsyncService cartAsyncService;

    @Autowired
    @Qualifier("redis")
    private RedisTemplate redisTemplate;

    @Value("${ware.url}")
    private String wareUrl;
    //添加订单信息
    public  Long addOrderInfo(OrderInfo orderInfo,String userId) {
        orderInfo.sumTotalAmount();
        orderInfo.setUserId(Long.parseLong(userId));
        orderInfo.setOrderStatus(OrderStatus.UNPAID.name());
        String outTradeNo = "ATGUIGU"+System.currentTimeMillis();
                new Random().nextInt(100);
        orderInfo.setOutTradeNo(outTradeNo);
        //订单描述
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        StringBuilder sb = new StringBuilder();
        for (OrderDetail orderDetail : orderDetailList) {
                sb.append(orderDetail.getSkuName());
        }
        if(sb.length() > 100){
            orderInfo.setTradeBody(sb.substring(0,100));
        }else{
            orderInfo.setTradeBody(sb.toString());
        }
        //创建时间
        orderInfo.setCreateTime(new Date());
        //销毁时间
        Calendar instance = Calendar.getInstance();
        instance.add(Calendar.HOUR,2);
        orderInfo.setExpireTime(instance.getTime());
        orderInfoMapper.insert(orderInfo);
        for (OrderDetail orderDetail : orderDetailList) {
            orderDetail.setOrderId(orderInfo.getId());
            orderDetailsMapper.insert(orderDetail);
        }
        //删除数据库购物车
        QueryWrapper<CartInfo> wrapper = new QueryWrapper<>();
        wrapper.eq("user_id",orderInfo.getUserId());
        List<String> SkuIdList = orderDetailList.stream().map(orderDetail -> {
            return orderDetail.getSkuId().toString();
        }).collect(Collectors.toList());
        wrapper.in("sku_id",SkuIdList.toArray());
        cartAsyncService.deleteAsyncCart(wrapper);
        //删除缓存购物车
        redisTemplate.boundHashOps(RedisConst.USER_KEY_PREFIX+userId+RedisConst.USER_CART_KEY_SUFFIX).delete(SkuIdList.toArray());
        return orderInfo.getId();
    }

    //检查仓库是否有货
    public boolean hasStock(Long skuId,Integer skuNum) {
        String isHasStock = HttpClientUtil.doGet(wareUrl + "hasStock?skuId=" + skuId + "&num=" + skuNum);
        return "1".equals(isHasStock);
    }

    //超过时间取消订单
    public void CancelOrder(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        if(orderInfo!=null&&orderInfo.getOrderStatus().equals(OrderStatus.UNPAID.name())){
            orderInfo.setOrderStatus(OrderStatus.CLOSED.name());
            orderInfo.setProcessStatus(OrderStatus.CLOSED.name());
            orderInfoMapper.updateById(orderInfo);
        }
    }

    //获取订单信息
    public OrderInfo getOrderInfo(Long orderId) {
        OrderInfo orderInfo = orderInfoMapper.selectById(orderId);
        return orderInfo;
    }


    public Map initWare(OrderInfo orderInfo) {
        Map map = new HashMap();
        map.put("orderId",orderInfo.getId());
        map.put("consignee",orderInfo.getConsignee());
        map.put("consigneeTel",orderInfo.getConsigneeTel());
        map.put("deliveryAddress",orderInfo.getDeliveryAddress());
        map.put("orderComment",orderInfo.getOrderComment());
        map.put("paymentWay",orderInfo.getPaymentWay());
        map.put("trackingNo",orderInfo.getTrackingNo());
        map.put("createTime",new Date());
        map.put("wareId",orderInfo.getWareId());
        List<Map> mapList = new ArrayList<>();
        List<OrderDetail> orderDetailList = orderInfo.getOrderDetailList();
        for (int i = 0; i < orderDetailList.size(); i++) {
            OrderDetail orderDetail = orderDetailList.get(i);
            Map detailsMap = new HashMap();
            detailsMap.put("skuId",orderDetail.getSkuId());
            detailsMap.put("skuName",orderDetail.getSkuName());
            detailsMap.put("skuNum",orderDetail.getSkuNum());
            mapList.add(detailsMap);
        }
        map.put("details",mapList);

        return map;
    }

    //拆单 [{"wareId":"1","skuIds":["2"]},{"wareId":"2","skuIds":["1"]}]
    @Transactional
    public List<OrderInfo> orderSplit(Long orderId, String wareSkuMap) {

        //订单详情表   skuId 1  skuId 5   同一张订单里
        //1:订单主表 原订单是不变了  原订单父订单 产生2张子订单   保存2条新的订单主表
        //2:订单详情表  修改订单主表的外键

        List<Map> mapList = JSONObject.parseArray(wareSkuMap, Map.class);

        //原订单
        OrderInfo originOrderInfo = orderInfoMapper.selectById(orderId);
        //原订单详情集合
        List<OrderDetail> originOrderDetailList = orderDetailsMapper.selectList(new QueryWrapper<OrderDetail>().eq("order_id",orderId));

        //
        List<OrderInfo> subOrderInfoList = new ArrayList<>();
        //[{"wareId":"1","skuIds":["5","6"]},{"wareId":"2","skuIds":["1"]}]
        if(originOrderInfo!=null&&originOrderDetailList!=null) {
            for (Map map : mapList) {
                //子订单主表
                OrderInfo subOrderInfo = new OrderInfo();
                BeanUtils.copyProperties(originOrderInfo, subOrderInfo);
                String wareId = (String) map.get("wareId");
                subOrderInfo.setWareId(wareId);
                // id 设置 null
                subOrderInfo.setId(null);
                //设置父订单的ID
                subOrderInfo.setParentOrderId(originOrderInfo.getId());

                List<OrderDetail> orderDetailList = new ArrayList<>();


                for (OrderDetail orderDetail : originOrderDetailList) {
                    List<String> skuIds = (List<String>) map.get("skuIds");
                    for (String skuId : skuIds) {
                        if (skuId.equals(orderDetail.getSkuId())) {
                            //订单详情表  修改订单主表的外键
                            orderDetailList.add(orderDetail);
                        }
                    }
                }
                //子订单总金额
                subOrderInfo.setOrderDetailList(orderDetailList);
                subOrderInfo.sumTotalAmount();
                //保存子订单主表
                orderInfoMapper.insert(subOrderInfo);
                //update order_detail set order_id = 16 where id in (x,x,x,)
                //更新子订单详情表 外键（批量)
                OrderDetail orderDetail = new OrderDetail();
                orderDetail.setOrderId(subOrderInfo.getId());
                List<Long> ids = orderDetailList.stream().map(OrderDetail::getId)
                        .collect(Collectors.toList());
                orderDetailsMapper.update(orderDetail, new QueryWrapper<OrderDetail>()
                        .in("id", ids));

                //追加子订单结果
                subOrderInfoList.add(subOrderInfo);
            }
            //将原订单的状态改成订单已折单
        }

        return subOrderInfoList;
    }
}
